

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.Scanner;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

import com.googlecode.javacpp.Loader;
import com.googlecode.javacv.*;
import com.googlecode.javacv.cpp.*;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_calib3d.*;
import static com.googlecode.javacv.cpp.opencv_objdetect.*;
import static com.googlecode.javacv.cpp.opencv_highgui.*;

public class Demo extends CanvasFrame{
	
	Image resImg;
	
	static JLabel origDisplay, detectDisplay;
	
	static String sourceURL;
	
	static int sel;
	
	static int dec = 0;
	
	static String cusURL;
	
	Demo demoframe;
	
	public Demo(String title){
		super(title);
		setSize(800, 400);
		setDefaultCloseOperation(EXIT_ON_CLOSE);

		Container c = getContentPane();
		c.setLayout(new FlowLayout());

		JButton openButton = new JButton("Open Media Resource");
		JButton openStream = new JButton("Open Live Cam");
		JButton chooseDec = new JButton("Custom Marker");
		origDisplay = new JLabel();
		detectDisplay  = new JLabel();

		// Create a file chooser that opens up as an Open dialog
		chooseDec.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				JFileChooser chooser = new JFileChooser();
				chooser.setMultiSelectionEnabled(true);
				int option = chooser.showOpenDialog(Demo.this);
				if (option == JFileChooser.APPROVE_OPTION) {
					File sf = chooser.getSelectedFile();
					
					resImg = Toolkit.getDefaultToolkit().getImage(sf.toString()).getScaledInstance(300,-1,Image.SCALE_SMOOTH);
					System.out.println(sf.toString());
				
					cusURL = sf.toString();
					
					
				}
				else {
					origDisplay.setText("You canceled.");
				}
			}
		});
		
		openStream.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				try{
					detectFace(getDF(),  null, 2);
				} catch (Exception ex) {
					// TODO Auto-generated catch block
					ex.printStackTrace();
				} finally {}
			}
		});
		
		openButton.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent ae) {
				JFileChooser chooser = new JFileChooser();
				chooser.setMultiSelectionEnabled(true);
				int option = chooser.showOpenDialog(Demo.this);
				if (option == JFileChooser.APPROVE_OPTION) {
					File sf = chooser.getSelectedFile();
					
					String filelist = sf.getName();
					
					resImg = Toolkit.getDefaultToolkit().getImage(sf.toString()).getScaledInstance(300,-1,Image.SCALE_SMOOTH);
					System.out.println(sf.toString());
					origDisplay.setIcon(new ImageIcon(resImg));
					sourceURL = sf.toString();
					if (sourceURL != null){
						if(checkFormat(sf.toString()).equals("jpg")){
							try{
								detectFace(getDF(),  sourceURL, 3);
							} catch (Exception ex) {
								// TODO Auto-generated catch block
								ex.printStackTrace();
							} finally {}
						} if (checkFormat(sf.toString()).equals("1")){
							try{
								detectFace(getDF(),  sourceURL, 1);
							} catch (Exception ex) {
								// TODO Auto-generated catch block
								ex.printStackTrace();
							} finally {}
						}
					}
					
				}
				else {
					origDisplay.setText("You canceled.");
				}
			}
		});
		
		JPanel jp = new JPanel(new GridLayout(3,1));
		c.add(jp, BorderLayout.SOUTH);
		jp.add(openButton);
		jp.add(openStream);
		jp.add(chooseDec);
		c.add(origDisplay, BorderLayout.NORTH);
	}
	
	void setDF(Demo df){
		demoframe = df;
	}
	
	Demo getDF(){
		return demoframe;
	}
	
	public String checkFormat(String url){
		String r = "";
		if(url.substring(url.length()-3, url.length()).equals("jpg")){
			r = "jpg";
		} else if (url.substring(url.length()-3, url.length()).equals("wmv") || url.substring(url.length()-3, url.length()).equals("avi")){
			r = "1";
		} else {
			r = null;
		}
		return r;
	}
	
	
    public static void main(String[] args) throws Exception {

        Demo frame = new Demo("Face Detection");
        frame.setDF(frame);

    }
    
    
    //private static void detectFace(Demo frame, CvHaarClassifierCascade classifier, String url) throws Exception{
    private static void detectFace(Demo frame,  String url, int sel) throws Exception{
    	System.out.println("detectFace running" + sel); 
    	// We can "cast" Pointer objects by instantiating a new object of the desired class.
    	String classifierName = "C:\\OpenCV\\data\\haarcascades\\haarcascade_frontalface_alt.xml";
        CvHaarClassifierCascade classifier = new CvHaarClassifierCascade(cvLoad(classifierName));
        if (classifier.isNull()) {
            System.err.println("Error loading classifier file \"" + classifierName + "\".");
            System.exit(1);
        }
    	try{
    		BufferedImage hat = null;
            BufferedImage bg = null;
            if (cusURL!=null){
            	hat = javax.imageio.ImageIO.read(new File(cusURL));
            	dec = 1;
            }
    		
    		
    		OpenCVFrameGrabber grabber = null;
    		OpenCVFrameGrabber Camgrabber = null;
            IplImage img = null;
            boolean isImage = false;
    		if(sel != 3){
    			if (sel == 1){
    				grabber = new OpenCVFrameGrabber(url);
    				grabber.start();
    				detectDisplay.setVisible(false);}
    			else if (sel == 2){
    				Camgrabber = new OpenCVFrameGrabber(0);
    				Camgrabber.start();
    				detectDisplay.setVisible(false);}
    		}
    		else{
    			img=cvLoadImage(url,1);
    			isImage = true;
    		}


    		CvFont font = new CvFont(CV_FONT_HERSHEY_PLAIN, 1, 1);

    		IplImage grabbedImage = null;
    		if (sel == 1){
    			grabbedImage = grabber.grab();
    			detectDisplay.setVisible(false);
    			
    			
    		}
    		else if (sel == 2)
    			grabbedImage = Camgrabber.grab();
    		else
    			grabbedImage = img.clone();
    		int width  = grabbedImage.width();
    		int height = grabbedImage.height();
    		IplImage grayImage    = IplImage.create(width, height, IPL_DEPTH_8U, 1);

    		CvMemStorage storage = CvMemStorage.create();

    		while (true/*frame.isVisible() && (grabbedImage = grabber.grab()) != null*/) {

    			if (isImage == false){
    				if (sel == 1){
    					if (frame.isVisible() && (grabbedImage = grabber.grab()) == null)
    						break;
    				}
    				else{
    					if (frame.isVisible() && (grabbedImage = Camgrabber.grab()) == null)
    						break;}
    			}

    			// Let's try to detect some faces! but we need a grayscale image...
    			cvCvtColor(grabbedImage, grayImage, CV_BGR2GRAY);
    			CvSeq faces = cvHaarDetectObjects(grayImage, classifier, storage,
    					1.1, 3, CV_HAAR_DO_CANNY_PRUNING);
    			int total = faces.total();
    			cvRectangle(grabbedImage, cvPoint(0, 0), cvPoint(200, 35), CvScalar.BLACK, CV_FILLED, CV_AA, 0);
    			cvPutText(grabbedImage, (total)+" face(s) detected" , cvPoint(20,20), font, CV_RGB(255,255,255));
    			for (int i = 0; i < total; i++) {
    				CvRect r = new CvRect(cvGetSeqElem(faces, i));
    				int x = r.x(), y = r.y(), w = r.width(), h = r.height();
    				if (dec != 1)
    					cvRectangle(grabbedImage, cvPoint(x, y), cvPoint(x+w, y+h), CvScalar.RED, 1, CV_AA, 0);

    				cvPutText(grabbedImage, "face"+i , cvPoint(x, y + h + 15), font, CV_RGB(255,255,255));
    			}
    			bg = grabbedImage.getBufferedImage();
                
                if (dec == 1)
                	for (int i = 0; i < total; i++) {
                		CvRect r = new CvRect(cvGetSeqElem(faces, i));
                		int x = r.x(), y = r.y(), w = r.width(), h = r.height();
                    
                		Graphics g = bg.getGraphics();
                		g.drawImage(hat, x , y-h/2, w, (int)(h*1.5),null);
                	}
    			frame.showImage(bg);

    			if (sel == 3)break;
    			else
    				cvClearMemStorage(storage);
    		}
    		if (sel == 2){
    			Camgrabber.stop();
    			frame.dispose();
    		}
    		if (sel == 1){
    			grabber.stop();
    			frame.dispose();
    		}
    	} finally {

    	} 
    }
}